package com.bootx.job;

import com.bootx.dao.LotteryRecordDao;
import com.bootx.entity.Config;
import com.bootx.entity.LotteryRecord;
import com.bootx.entity.OpenAiConfig;
import com.bootx.predict.pojo.PredictPlugin;
import com.bootx.predict.pojo.PredictionResult;
import com.bootx.predict.pojo.RedPacketBatch;
import com.bootx.service.*;
import com.bootx.util.DateUtils;
import com.bootx.util.JsonUtils;
import com.bootx.util.lottery.LotteryUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author black
 */
@Component
public class LotteryJob {

    @Resource
    private LotteryRecordService lotteryRecordService;
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private LotteryRecordDao lotteryRecordDao;

    @Resource
    private List<PredictPlugin> predictPlugins = new ArrayList<PredictPlugin>();

    @Resource
    private ConfigService configService;
    @Resource
    private RedisService redisService;

    /**
     * 获取最新一组的数据
     */
    @Scheduled(fixedRate = 1000*10)
    public void run(){
        List<Map<String, Object>> maps1 = jdbcTemplate.queryForList("select code from lottery;");
        for (Map<String, Object> stringObjectMap : maps1) {
            List<Map<String, Object>> maps = jdbcTemplate.queryForList("select drawCode,DATE_FORMAT(drawTime,'%Y-%m-%d %H:%i:%s') drawTime from lotteryrecord where lotteryCode=? order by sn desc limit 1",stringObjectMap.get("code"));
            if(!maps.isEmpty()){
                Map<String, Object> first = maps.getFirst();
                Object drawCode = first.get("drawCode");
                String drawTime = first.get("drawTime") + "";
                if(drawCode==null && new Date().compareTo(DateUtils.formatStringToDate(drawTime,"yyyy-MM-dd HH:mm:ss"))>=0){
                    Long lotteryCode = Long.valueOf(stringObjectMap.get("code")+"");
                    Map<String, LotteryRecord> data = LotteryUtils.getData(lotteryCode, 0);
                    LotteryRecord current = data.get("current");
                    LotteryRecord next = data.get("next");
                    try {
                        lotteryRecordService.save(current);
                        lotteryRecordService.save(next);
                        Integer i = jdbcTemplate.queryForObject("select count(id) from lotteryrecord where lotteryCode=? and predictResult is null and sn=? order by sn desc limit 1", Integer.class, lotteryCode,next.getSn());
                        if(i!=null && i>0){
                            lotteryRecordService.predict(lotteryCode,next.getSn());
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    redisService.delete("lottery:"+stringObjectMap.get("code"));
                }
            }
        }
    }

    @Scheduled(cron = "59 23 * * * *")
    //@Scheduled(fixedRate = 1000*60)
    public void history(){
        List<Map<String, Object>> maps1 = jdbcTemplate.queryForList("select code from lottery;");
        maps1.forEach(stringObjectMap -> {
            List<LotteryRecord> history = LotteryUtils.history(Long.valueOf(stringObjectMap.get("code")+""));
            for (LotteryRecord lotteryRecord : history) {
                try {
                    lotteryRecordService.save(lotteryRecord);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            redisService.delete("lottery:"+stringObjectMap.get("code"));
        });
    }

    //@Scheduled(fixedRate = 1000*20)
    public void predict(){
        long current = 13642305L;
        for (long i = current; i < current+1000; i++) {
            List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from lotteryrecord where predictResult is null and lotteryCode=? and sn=?", 10036L, i + 1);
            if(!maps.isEmpty()){
                predict(10036L,i+1);
            }
        }
    }

    public void predict(Long lotteryCode,Long sn) {
        Config config = configService.find(2L);
        List<PredictPlugin> predictPluginList = predictPlugins.stream().filter(item -> StringUtils.equals(item.getName(), "basePredict")).toList();
        if(predictPluginList.isEmpty()){
            System.out.println("不存在该预测方法");
            return;
        }
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT * FROM (SELECT sn `batchId`,openInfo FROM lotteryrecord where lotteryCode=? and sn<? ORDER BY batchId DESC LIMIT ?) AS recent ORDER BY batchId ASC;", lotteryCode,sn,config.getPredictionCount());
        List<RedPacketBatch> list = new ArrayList<>();
        maps.forEach(map -> {
            RedPacketBatch redPacketBatch = new RedPacketBatch();
            redPacketBatch.setBatchId(Long.valueOf(map.get("batchId").toString()));
            List<RedPacketBatch.RedPacketDetail> redPackets = JsonUtils.toObject(map.get("openInfo")+"", new TypeReference<List<RedPacketBatch.RedPacketDetail>>() {
            });
            redPackets.sort(Comparator.comparingInt(RedPacketBatch.RedPacketDetail::getIndex));
            List<RedPacketBatch.RedPacketDetail> collect = redPackets.stream()
                    .sorted(Comparator.comparingInt(rp -> -rp.getIndex()))
                    .limit(config.getWalletIndex())
                    .sorted(Comparator.comparingInt(RedPacketBatch.RedPacketDetail::getIndex))
                    .collect(Collectors.toList());
            // 去掉最后几个
            for(int i=0;i<config.getWalletIndex()-1;i++){
                collect.removeLast();
            }
            int newIndex = 1000;
            for (RedPacketBatch.RedPacketDetail rp : collect) {
                rp.setIndex(newIndex++);
            }
            redPacketBatch.setRedPackets(collect);
            list.add(redPacketBatch);
        });
        Set<Integer> indexs = new HashSet<>();
        indexs.add(1000);
        for (int i = 0; i < list.size(); i++) {
            indexs.add(1000+i);
        }
        List<PredictionResult> results = predictPluginList.getFirst().predict(list,indexs);
        // 提取出概率最大的一项
        PredictionResult best = results.stream()
                .max(Comparator.comparingDouble(PredictionResult::getOddProbability))
                .orElse(null);
        assert best != null;
        LotteryRecord lotteryRecord = lotteryRecordDao.find("sn", sn);
        if(best.getOddProbability()<0.5){
            lotteryRecord.setPredictResult(0);
        } else if (best.getOddProbability()>=0.5) {
            lotteryRecord.setPredictResult(1);
        }
        // 获取到预测的是哪个位置
        lotteryRecord.setPredictPosition(1);
        // 获取到预测的是哪个位置
        String drawCode = lotteryRecord.getDrawCode();
        String[] split = drawCode.split(",");
        int position = split.length-config.getWalletIndex();
        if(position>=0 && lotteryRecord.getPredictResult()!=null){
            String s = split[position];
            lotteryRecord.setWin(Integer.parseInt(s)%2==lotteryRecord.getPredictResult());
        }
        lotteryRecordService.update(lotteryRecord);
    }
}
